load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
load("//bazel:canbench.bzl", "rust_canbench")
load("//bazel:canisters.bzl", "rust_canister")
load("//bazel:defs.bzl", "rust_ic_test", "rust_ic_test_suite_with_extra_srcs")
load("//bazel:prost.bzl", "generated_files_check")

package(default_visibility = ["//visibility:public"])

filegroup(
    name = "protos",
    srcs = glob(["proto/**/*.proto"]),
)

DEPENDENCIES = [
    # Keep sorted.
    "//rs/crypto/node_key_validation",
    "//rs/crypto/sha2",
    "//rs/crypto/utils/basic_sig",
    "//rs/crypto/utils/ni_dkg",
    "//rs/nervous_system/access_list",
    "//rs/nervous_system/chunks",
    "//rs/nervous_system/clients",
    "//rs/nervous_system/common",
    "//rs/nervous_system/rate_limits",
    "//rs/nervous_system/string",
    "//rs/nervous_system/temporary",
    "//rs/nervous_system/time_helpers",
    "//rs/nns/common",
    "//rs/nns/constants",
    "//rs/protobuf",
    "//rs/registry/canister/api",
    "//rs/registry/canister/chunkify",
    "//rs/registry/keys",
    "//rs/registry/node_provider_rewards",
    "//rs/registry/routing_table",
    "//rs/registry/subnet_features",
    "//rs/registry/subnet_type",
    "//rs/registry/transport",
    "//rs/rust_canisters/dfn_candid",
    "//rs/rust_canisters/dfn_core",
    "//rs/rust_canisters/dfn_http_metrics",
    "//rs/rust_canisters/on_wire",
    "//rs/types/base_types",
    "//rs/types/management_canister_types",
    "//rs/types/types",
    "//rs/utils",
    "@crate_index//:build-info",
    "@crate_index//:candid",
    "@crate_index//:futures",
    "@crate_index//:hex",
    "@crate_index//:ic-cdk",
    "@crate_index//:ic-certified-map",
    "@crate_index//:ic-metrics-encoder",
    "@crate_index//:ic-stable-structures",
    "@crate_index//:idna",
    "@crate_index//:ipnet",
    "@crate_index//:lazy_static",
    "@crate_index//:leb128",
    "@crate_index//:maplit",
    "@crate_index//:prost",
    "@crate_index//:serde",
    "@crate_index//:url",
]

DEV_DEPENDENCIES = [
    # Keep sorted.
    "//rs/canister_client/sender",
    "//rs/config",
    "//rs/crypto/node_key_generation",
    "//rs/crypto/test_utils/ni-dkg",
    "//rs/crypto/test_utils/reproducible_rng",
    "//rs/crypto/tree_hash",
    "//rs/interfaces/registry",
    "//rs/nervous_system/common/test_keys",
    "//rs/nns/test_utils",
    "//rs/registry/fake",
    "//rs/registry/nns_data_provider",
    "//rs/registry/proto_data_provider",
    "//rs/replica_tests",
    "//rs/rust_canisters/canister_test",
    "//rs/test_utilities",
    "//rs/test_utilities/compare_dirs",
    "//rs/test_utilities/types",
    "//rs/types/types_test_utils",
    "@crate_index//:assert_matches",
    "@crate_index//:candid_parser",
    "@crate_index//:itertools",
    "@crate_index//:pretty_assertions",
    "@crate_index//:rand",
    "@crate_index//:rand_distr",
    "@crate_index//:serde_json",
    "@crate_index//:tempfile",
    "@crate_index//:tokio",
]

MACRO_DEPENDENCIES = [
    # Keep sorted.
    "//rs/nervous_system/common/build_metadata",
]

DEV_MACRO_DEPENDENCIES = [
    # Keep sorted.
    "//rs/nns/test_utils_macros",
]

BUILD_DEPENDENCIES = [
    # Keep sorted.
    "@crate_index//:build-info-build",
]

POCKET_IC_DEPS = [
    "//packages/pocket-ic",
]

POCKET_IC_DATA = [
    "//rs/pocket_ic_server:pocket-ic-server",
]

POCKET_IC_ENV = {
    "POCKET_IC_BIN": "$(rootpath //rs/pocket_ic_server:pocket-ic-server)",
}

ALIASES = {}

LIB_SRCS = glob(
    ["src/**/*.rs"],
    exclude = ["**/*tests*/**"],
)

cargo_build_script(
    name = "build_script",
    srcs = ["build.rs"],
    aliases = ALIASES,
    data = [],  # build script data (e.g. template files) goes here
    version = "0.9.0",
    deps = BUILD_DEPENDENCIES,
)

rust_library(
    name = "canister",
    srcs = LIB_SRCS,
    aliases = ALIASES,
    crate_name = "registry_canister",
    proc_macro_deps = MACRO_DEPENDENCIES,
    version = "0.9.0",
    deps = DEPENDENCIES + [":build_script"],
)

rust_library(
    name = "canister--canbench_feature",
    srcs = LIB_SRCS,
    aliases = ALIASES,
    crate_features = ["canbench-rs"],
    crate_name = "registry_canister",
    proc_macro_deps = MACRO_DEPENDENCIES,
    version = "0.9.0",
    deps = DEPENDENCIES + [
        ":build_script",
        "@crate_index//:canbench-rs",
        "@crate_index//:rand",
        "@crate_index//:rand_chacha",
    ],
)

rust_library(
    name = "canister--test_feature",
    srcs = LIB_SRCS,
    aliases = ALIASES,
    crate_features = ["test"],
    crate_name = "registry_canister",
    proc_macro_deps = MACRO_DEPENDENCIES,
    version = "0.9.0",
    deps = DEPENDENCIES + [":build_script"],
)

rust_canister(
    name = "registry-canister",
    srcs = ["canister/canister.rs"],
    aliases = ALIASES,
    compile_data = ["canister/registry.did"],
    proc_macro_deps = MACRO_DEPENDENCIES,
    service_file = ":canister/registry.did",
    deps = DEPENDENCIES + [
        ":build_script",
        ":canister",
    ],
)

rust_canister(
    name = "registry-canister-test",
    srcs = ["canister/canister.rs"],
    aliases = ALIASES,
    compile_data = ["canister/registry_test.did"],
    crate_features = ["test"],
    proc_macro_deps = MACRO_DEPENDENCIES,
    service_file = ":canister/registry_test.did",
    deps = DEPENDENCIES + [
        ":build_script",
        ":canister--test_feature",
    ],
)

rust_ic_test(
    name = "registry_canister_canister_test",
    srcs = glob(["canister/*.rs"]),
    compile_data = ["canister/registry.did"],
    crate_root = "canister/canister.rs",
    proc_macro_deps = MACRO_DEPENDENCIES + DEV_MACRO_DEPENDENCIES,
    deps = DEV_DEPENDENCIES + DEPENDENCIES + [
        ":build_script",
        ":canister",
    ],
)

rust_ic_test(
    name = "registry_canister_test_canister_test",
    srcs = glob(["canister/*.rs"]),
    compile_data = ["canister/registry_test.did"],
    crate_features = ["test"],
    crate_root = "canister/canister.rs",
    proc_macro_deps = MACRO_DEPENDENCIES + DEV_MACRO_DEPENDENCIES,
    deps = DEV_DEPENDENCIES + DEPENDENCIES + [
        ":build_script",
        ":canister--test_feature",
    ],
)

rust_test(
    name = "registry_canister_test",
    srcs = glob(["src/**"]),
    proc_macro_deps = DEV_MACRO_DEPENDENCIES,
    deps = DEPENDENCIES + DEV_DEPENDENCIES,
)

rust_ic_test_suite_with_extra_srcs(
    name = "registry_canister_integration_test",
    srcs = glob(
        ["tests/*.rs"],
        exclude = [
            # Keep sorted.
            "tests/check_generated_files.rs",
            "tests/mod.rs",
        ],
    ),
    data = [
        # Keep sorted.
        ":registry-canister",
        ":registry-canister-test",
        "//rs/nns/cmc:cycles-minting-canister",
        "//rs/universal_canister/impl:universal_canister.wasm.gz",
    ] + POCKET_IC_DATA,
    env = {
        # Keep sorted.
        "CARGO_MANIFEST_DIR": "rs/registry/canister",
        "CYCLES_MINTING_CANISTER_WASM_PATH": "$(rootpath //rs/nns/cmc:cycles-minting-canister)",
        "REGISTRY_CANISTER_WASM_PATH": "$(rootpath :registry-canister)",
        "REGISTRY_CANISTER_TEST_WASM_PATH": "$(rootpath :registry-canister-test)",
        "UNIVERSAL_CANISTER_WASM_PATH": "$(rootpath //rs/universal_canister/impl:universal_canister.wasm.gz)",
    } | POCKET_IC_ENV,
    extra_srcs = glob(["tests/common/*.rs"]),
    proc_macro_deps = DEV_MACRO_DEPENDENCIES,
    deps = DEPENDENCIES + DEV_DEPENDENCIES + [
        ":canister",
        "//rs/nervous_system/integration_tests:nervous_system_integration_tests",
        "//rs/state_machine_tests",
    ] + POCKET_IC_DEPS,
)

generated_files_check(
    name = "check_generated_files",
    srcs = ["tests/check_generated_files.rs"],
    data = [
        # Keep sorted.
        ":protos",
        "//rs/nns/common:protos",
        "//rs/protobuf:protos",
        "//rs/types/base_types:protos",
    ] + glob(["src/gen/**"]),
    manifest_dir = "rs/registry/canister",
    deps = [
        # Keep sorted.
        "//rs/registry/canister/protobuf_generator:lib",
        "//rs/test_utilities/compare_dirs",
        "@crate_index//:tempfile",
    ],
)

# Usage
# =====
#
# For benchmarking (see `canbench/canbench_results.yml`):
# ```
# bazel run //rs/registry/canister:registry-canbench
# ```
#
# For updating the results file:
# ```
# bazel run //rs/registry/canister:registry-canbench_update
# ```
#
# To run the test:
# ```
# bazel test //rs/registry/canister:registry-canbench_test
# ```
#
# Currently, updating the results file is not automated, and there are no tests to avoid
# regression. For now, we can use it as an example for benchmarking as part
# of an investigation of potential performance issues, or when we make a change that can affect
# the performance measured in this benchmark.
rust_canbench(
    name = "registry-canbench",
    srcs = ["canbench/main.rs"],
    add_test = True,
    results_file = "canbench/canbench_results.yml",
    deps = [
        # Keep sorted.
        ":canister--canbench_feature",
    ],
)
